﻿module HybridStreamReader

open System
open System.IO
open System.Text

type HybridStream(stream:Stream, encoding:Encoding) =
  inherit BinaryReader(stream, encoding)

  let Encoding _encoding = encoding
  let decoder _decoder = encoding.GetDecoder()

  let bufferSize = 1024
  let _LineBuffer : char[] = Array.zeroCreate bufferSize
    
  member this.ReadLine() : string =  
    let mutable pos = 0
    let mutable buf : char[] =  Array.zeroCreate 2
    let mutable stringBuffer : StringBuilder = null
    let mutable lineEndFound = false

    while not lineEndFound && base.Read(buf, 0, 2) > 0 do    
      if buf.[1] = '\r'
      then do
        // grab buf[0]        
        do _LineBuffer.[pos] <- buf.[0]
        do pos <- pos + 1
        // get the '\n'
        let ch : char = base.ReadChar()
        assert (ch = '\n')
        do lineEndFound <- true          
      elif buf.[0] = '\r'
      then      
        do lineEndFound <- true                
      else      
        do _LineBuffer.[pos] <- buf.[0]
        do _LineBuffer.[pos+1] <- buf.[1]
        do pos <- pos + 2;
        if (pos >= bufferSize)
        then
          do stringBuffer <- new StringBuilder(bufferSize + 80)
          do stringBuffer.Append(_LineBuffer, 0, bufferSize) |> ignore
          do pos <- 0      

    if stringBuffer = null
    then
        if pos > 0
        then new string(_LineBuffer, 0, pos);
        else if (lineEndFound) then String.Empty else null
    else        
        if pos > 0
        then do stringBuffer.Append(_LineBuffer, 0, pos)  |> ignore
        stringBuffer.ToString()      



